<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { FolderYellow, Top, Refresh, UploadFilled } from '@/util/icons'
// import Scrollbar from '@/components/Scrollbar.vue'
import type { Page } from '@/types'
import type { FileTable } from '@/types/file'
import { getFileList, addFile, floderScan, getFileSize, delFile } from './api'
import { dateFormat, getFormatDictMap } from '@/util/dict'
import AuthButton from '@/components/AuthButton.vue'
import AuthLink from '@/components/AuthLink.vue'
import FileIcon from './FileIcon.vue'
import { deepCopy } from '@/util/token'
import { ElMessage, ElNotification, type UploadFile } from 'element-plus'
import Pagination from '@/components/Pagination.vue'
/* 获取对应的字典信息 */
const tableDict = ref<Map<string, string>>()
const statusDict = ref<Map<string, string>>()
const page = ref<Page<FileTable>>({
  num: 1,
  size: 50,
  rows: [],
  count: 0
})
const loading = ref<boolean>(false)
const parentList = ref<FileTable[]>([])
/* 搜索 */
/* 是否展示搜索栏 */
const showSearchBar = ref<boolean>(true)
const searchForm = ref<FileTable>({
  name: '',
  parent: 0
})
// 页面排序
// let orderBy: any = {}
// 获取页面数据
function getPageData() {
  if (loading.value) {
    return
  }
  loading.value = true
  let data: any
  getFileList(page.value, searchForm.value)
    .then((d) => {
      data = d.data
    })
    .finally(() => {
      setTimeout(() => {
        page.value = data as Page<FileTable>
        loading.value = false
      }, 100)
    })
}

/* 数据选择器 */
const selectData = ref<FileTable[]>([])
function onSelect(data: FileTable[]) {
  selectData.value = data
}
onMounted(() => {
  getFormatDictMap('sys_file', 'head').then((d) => {
    tableDict.value = d
  })
  getFormatDictMap('sys_file_status', 'val').then((d) => {
    statusDict.value = d
  })
  getPageData()
})

// 格式化文件大小
function formatSize(size: number) {
  if (size < 1024) {
    return `${size.toFixed(2)} B`
  } else if (size < 1024 ** 2) {
    return `${(size / 1024).toFixed(2)} kB`
  } else if (size < 1024 ** 3) {
    return `${(size / 1024 ** 2).toFixed(2)} MB`
  } else if (size < 1024 ** 4) {
    return `${(size / 1024 ** 3).toFixed(2)} GB`
  } else {
    return `${(size / 1024 ** 4).toFixed(2)} TB`
  }
}
// 打开文件夹
function openFolder(file: FileTable) {
  if (file.fType !== 'dir') {
    return
  }
  parentList.value.push(deepCopy(file))
  searchForm.value.parent = file.id
  getPageData()
}

// 返回上一级目录
function back() {
  let file = parentList.value.pop()
  searchForm.value.parent = file?.parent
  getPageData()
}

// 去到某个目录
function go(fId: number) {
  searchForm.value.parent = fId
  if (fId == 0) {
    parentList.value = []
  } else {
    let index = 1
    for (let item of parentList.value) {
      if (item.id == fId) {
        break
      }
      index++
    }
    parentList.value.splice(index)
  }
  getPageData()
}

// 文件夹扫描
function scan() {
  let fid = 0
  if (parentList.value.length > 0) {
    fid = parentList.value[parentList.value.length - 1].id!
  }
  let not = ElNotification({
    title: '扫描文件夹',
    message: '正在扫描中',
    duration: 0
  })
  floderScan(fid)
    .then((data) => {
      ElMessage.success(data.msg)
      getPageData()
    })
    .catch((data) => {
      ElMessage.error(data.msg)
    })
    .finally(() => {
      setTimeout(() => {
        not.close()
      }, 200)
    })
}

// 文件
const _addFile = ref<File | null>(null)
// 文件选择
// 文件选择
function onExceed() {
  ElMessage.warning('请先移除之前选择的文件')
}
function onChange(file: UploadFile) {
  _addFile.value = file.raw!
}
// 上传文件
// 打开上传窗口
function openUpload() {
  controlType.value = 'addFile'
  dialogTitle.value = '上传文件'
  dialogWidth.value = '60%'
  dialogVisible.value = true
}

// 弹窗控制
/* 对话框控制 */
const dialogVisible = ref<boolean>(false)
const dialogWidth = ref<string>('50%')
const controlType = ref<'none' | 'addDir' | 'del' | 'addFile'>('none')
const dialogTitle = ref('')

const EditData = ref<FileTable>({})
// 打开文件夹添加
function openAdd() {
  controlType.value = 'addDir'
  dialogTitle.value = '新建文件夹'
  dialogWidth.value = '300px'
  dialogVisible.value = true
  _addFile.value = null
  EditData.value = {
    name: '新建文件夹'
  }
}
// 添加文件函数
function add(type: 'file' | 'dir') {
  let fid = 0
  if (parentList.value.length > 0) {
    fid = parentList.value[parentList.value.length - 1].id!
  }
  let file: File | undefined = undefined
  if (type == 'file') {
    if (_addFile.value == null) {
      ElMessage.warning('请先选择文件')
      return
    }
    file = _addFile.value
  }
  addFile(fid, type, file, EditData.value.name)
    .then((data) => {
      ElMessage.success(data.msg)
      getPageData()
      dialogVisible.value = false
    })
    .catch((data) => {
      ElMessage.error(data.msg)
    })
}

const delData = ref<FileTable[]>([])
// 文件删除弹窗
function openDel(files: FileTable[]) {
  delData.value = deepCopy(files)
  controlType.value = 'del'
  dialogTitle.value = '删除'
  dialogWidth.value = '60%'
  dialogVisible.value = true
}

// 删除实际操作
function del() {
  let ids: number[] = delData.value.map((data) => {
    return data.id!
  })
  delFile(ids)
    .then((data) => {
      ElMessage.success(data.msg)
      getPageData()
      dialogVisible.value = false
    })
    .catch((data) => {
      ElMessage.error(data.msg)
    })
}

/**
 * 计算文件夹大小
 * @param file 文件数据
 */
function calculateFolderSize(file: FileTable) {
  getFileSize(file.id!).then((data) => {
    if (data.data.size == 0) {
      file.size = 0.001
    } else {
      file.size = data.data.size
    }
  })
}
</script>
<template>
  <div class="page-root">
    <div class="header">
      <el-row style="width: 65%; min-width: 500px">
        <el-col :span="3">
          <el-button
            class="up-button"
            @click="back"
            :icon="Top"
            :round="false"
            :disabled="parentList.length == 0"
          />
        </el-col>
        <el-col :span="18">
          <div class="path">
            <span class="path-item path-root" @click="go(0)">根目录</span>
            <span class="path-item" v-for="item in parentList" @click="go(item.id!)">
              / {{ item.name }}
            </span>
          </div>
        </el-col>
        <el-col :span="3"
          ><el-button @click="getPageData" :icon="Refresh" class="up-button"
        /></el-col>
      </el-row>
    </div>
    <div class="control">
      <AuthButton @click="openUpload" auth-tag="sys:file:upload"></AuthButton>
      <AuthButton @click="scan()" auth-tag="sys:file:scan"></AuthButton>
      <AuthButton disabled auth-tag="sys:file:create_file"></AuthButton>
      <AuthButton @click="openAdd" auth-tag="sys:file:create_dir"></AuthButton>
      <AuthButton
        :disabled="selectData.length == 0"
        @click="openDel(selectData)"
        auth-tag="sys:file:del"
      ></AuthButton>
    </div>
    <div class="ctx">
      <el-scrollbar>
        <el-table
          v-loading="loading"
          :data="page.rows"
          table-layout="auto"
          :stripe="true"
          row-key="id"
          @selection-change="onSelect"
        >
          <el-table-column type="selection" width="50" />
          <el-table-column min-width="300">
            <template #header>
              {{ tableDict?.get('name') || 'name' }}
            </template>
            <template #default="{ row }">
              <div class="info-row" @click="openFolder(row)">
                <span class="icon"
                  ><FolderYellow v-if="row['fType'] == 'dir'" />
                  <el-icon v-else>
                    <FileIcon :suffix="row['suffix']" />
                  </el-icon>
                </span>
                <span>{{ row.name }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column width="150px" align="center">
            <template #header>
              {{ tableDict?.get('createTime') || 'createTime' }}
            </template>
            <template #default="{ row }">
              <span>{{ dateFormat(row.createTime) }}</span>
            </template>
          </el-table-column>
          <el-table-column width="150px" align="center">
            <template #header>
              {{ tableDict?.get('createBy') || 'createBy' }}
            </template>
            <template #default="{ row }">
              <span>{{ row.createBy }}</span>
            </template>
          </el-table-column>
          <el-table-column align="center">
            <template #header>
              {{ tableDict?.get('size') || 'size' }}
            </template>
            <template #default="{ row }">
              <span v-if="row['fType'] == 'file' || row['size'] != 0">{{
                formatSize(row.size)
              }}</span>
              <span class="highlight-success" @click="calculateFolderSize(row)" v-else>计算</span>
            </template>
          </el-table-column>
          <el-table-column width="400px" align="center">
            <template #header> 操作 </template>
            <template #default="{ row }">
              <span class="buttons">
                <AuthLink @click="openDel([row])" auth-tag="sys:file:del" />
                <AuthLink disabled @click="" auth-tag="sys:file:download" />
                <AuthLink disabled @click="" auth-tag="sys:file:auth" />
                <AuthLink disabled @click="" auth-tag="sys:file:share" />
              </span>
            </template>
          </el-table-column>
        </el-table>
      </el-scrollbar>
    </div>
    <div class="footer">
      <el-row>
        <el-col :span="12">
          <!-- <span>文件总数:{{ page.count }} 共计大小：<span>{{  }}</span></span> -->
        </el-col>
        <el-col :span="12">
          <Pagination :page="page" :get-page-data="getPageData" />
        </el-col>
      </el-row>
    </div>
    <el-dialog
      destroy-on-close
      draggable
      :width="dialogWidth"
      v-model="dialogVisible"
      :title="dialogTitle"
      top="5%"
    >
      <el-row v-if="controlType == 'addDir'">
        <el-form style="width: 100%">
          <el-form-item label="名称">
            <el-input style="width: 100%" v-model="EditData.name"></el-input>
          </el-form-item>
        </el-form>
      </el-row>
      <el-row v-else-if="controlType == 'del'">
        <el-col>
          <div>
            <span class="highlight-danger">删除操作不可逆！！！是否继续操作？</span
            ><span>以下为即将删除的文件！！！请确认</span>
          </div>
          <el-scrollbar height="60vh" width="100%">
            <el-table :data="delData">
              <el-table-column>
                <template #header>
                  {{ tableDict?.get('name') || 'name' }}
                </template>
                <template #default="{ row }">
                  <div class="info-row">
                    <span class="icon"
                      ><FolderYellow v-if="row['fType'] == 'dir'" />
                      <el-icon v-else>
                        <FileIcon :suffix="row['suffix']" />
                      </el-icon>
                    </span>
                    <span>{{ row.name }}</span>
                  </div>
                </template>
              </el-table-column>
              <el-table-column width="150px" align="center">
                <template #header>
                  {{ tableDict?.get('createTime') || 'createTime' }}
                </template>
                <template #default="{ row }">
                  <span>{{ dateFormat(row.createTime) }}</span>
                </template>
              </el-table-column>
              <el-table-column width="150px" align="center">
                <template #header>
                  {{ tableDict?.get('createBy') || 'createBy' }}
                </template>
                <template #default="{ row }">
                  <span>{{ row.createBy }}</span>
                </template>
              </el-table-column>
            </el-table>
          </el-scrollbar>
        </el-col>
      </el-row>
      <el-row v-else-if="controlType == 'addFile'">
        <el-col>
          <div class="path">
            <span>当前路径 / </span>
            <span class="path-item path-root">根目录</span>
            <span class="path-item" v-for="item in parentList"> / {{ item.name }} </span>
          </div>
        </el-col>
        <el-col>
          <el-upload
            class="upload-demo"
            drag
            :auto-upload="false"
            style="width: 100%"
            :on-exceed="onExceed"
            :limit="1"
            :onChange="onChange"
          >
            <el-icon class="el-icon--upload"><upload-filled /></el-icon>
            <div class="el-upload__text">请拖动文件或是<em>点击上传</em></div>
            <template #tip>
              <div class="el-upload__tip"></div>
            </template>
          </el-upload>
        </el-col>
      </el-row>
      <template #footer>
        <el-row justify="center" v-if="controlType == 'addDir'">
          <el-button type="warning" @click="add('dir')">添加</el-button>
        </el-row>
        <el-row justify="center" v-else-if="controlType == 'del'">
          <el-button type="danger" @click="del">确认</el-button>
        </el-row>
        <el-row justify="center" v-else-if="controlType == 'addFile'">
          <el-button type="danger" @click="add('file')">上传</el-button>
        </el-row>
      </template>
    </el-dialog>
  </div>
</template>
<style scoped lang="less">
@import '@/assets/page_bgl.less';
@header-height: 60px;
@control-height: 40px;
@footer-height: 60px;
@path-header: 40px;
.header {
  height: @header-height;
  color: var(--el-color-info);

  .up-button {
    height: @path-header;
    width: 100%;
    font-size: 30px;
    border-radius: 0;
  }
  .path-root {
    margin-left: 20px;
  }
  .path {
    height: @path-header;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    vertical-align: middle;
    border: var(--el-border);
    border-right: none;
    border-left: none;
    line-height: @path-header - 2px;
  }
  .path-item {
    margin-right: 10px;
    cursor: pointer;
    &:hover {
      background: aliceblue;
    }
  }
}

.control {
  height: @control-height;
}
.ctx {
  height: calc(100% - @footer-height - @header-height - @control-height);
}
.footer {
  height: @footer-height;
  box-sizing: border-box;
  padding: 1px;
}
.info-row {
  height: 40px;
  display: flex;
  align-items: center;
  cursor: pointer;
  .icon {
    font-size: 30px;
    margin-right: 10px;
  }
  & > span {
    top: 0;
    line-height: 40px;
    height: 40px;
    display: inline-block;
  }
}
</style>
